#include "stm32f10x.h"

// 延时函数，微秒作为单位，利用系统嘀嗒定时器，72MHz，一次嘀嗒 1/72 us
void Delay_us(uint16_t us)
{
	// 1.装载一个计数值，72*us
	SysTick->LOAD = 72 * us;
	// 2.配置，使用系统时钟（1），计数结束不产生中断（0），使能定时器
	SysTick->CTRL |= 0x05;
	// 3.等待计数值变为0，判断CTRL标志位COUNTFLAG是否为1
	while ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG) == 0)
	{
	}

	// 4.关闭定时器
	SysTick->CTRL &= ~SysTick_CTRL_ENABLE;
}

void Delay_ms(uint16_t ms)
{
	while (ms--)
	{
		Delay_us(1000);
	}
}

void Delay_s(uint16_t s)
{
	while (s--)
	{
		Delay_ms(1000);
	}
}

int main(void)
{

#if 1
	// 对地址进行优化，使用宏定义
	// 1.时钟配置
	// RCC寄存器的基地址 0x4002 1000  APB2偏移地址 0x18，使能GPIOA的时钟
	RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;

	// 2.GPIO工作模式配置
	// GPIOA的基地址 0x4001 0800，配置PA1/PA2/PA3的 0011 输出模式
	// PA1的配置
	GPIOA->CRL &= ~GPIO_CRL_CNF1;
	GPIOA->CRL |= GPIO_CRL_MODE1;
	// PA2的配置
	GPIOA->CRL &= ~GPIO_CRL_CNF2;
	GPIOA->CRL |= GPIO_CRL_MODE2;
	// PA3的配置
	GPIOA->CRL &= ~GPIO_CRL_CNF3;
	GPIOA->CRL |= GPIO_CRL_MODE3;

	// 3.PA1/PA2/PA3输出高电平
	GPIOA->ODR |= (GPIO_ODR_ODR1 | GPIO_ODR_ODR2 | GPIO_ODR_ODR3);
	// 4.用一个死循环保持状态
	while (1)
	{
		// led1
		GPIOA->ODR &= ~GPIO_ODR_ODR1;
		Delay_ms(500);
		GPIOA->ODR |= GPIO_ODR_ODR1;

		// led1
		GPIOA->ODR &= ~GPIO_ODR_ODR2;
		Delay_ms(500);
		GPIOA->ODR |= GPIO_ODR_ODR2;

		// led1
		GPIOA->ODR &= ~GPIO_ODR_ODR3;
		Delay_ms(500);
		GPIOA->ODR |= GPIO_ODR_ODR3;
	}
#endif
}
